using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
//using System.Web.UI.Design.WebControls;
using System.Drawing.Design;
using System.Collections.Specialized;
using System.Data;

namespace NWS {
	[DefaultEvent("SelectedIndexChanged")]
	[SupportsEventValidation]
	[Designer("System.Web.UI.Design.WebControls.GridViewDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") ]
	[ControlValueProperty("SelectedValue")]
	//[AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	//[AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
	[ToolboxData("<{0}:InsertableGrid runat=server></{0}:InsertableGrid>")]
	public class InsertableGrid : GridView {
		protected static readonly object EventItemInserting = new object();
		protected static readonly object EventItemInserted = new object();

		[Browsable(true), DefaultValue("true"), Category("Behavior")]
		public bool AllowInsert {
			get { object o = ViewState["_InsOk"]; return o == null ? true : (bool)o; }
			set { ViewState["_InsOk"] = value; }
		}

		private IOrderedDictionary _InsertValues = null;
		protected IOrderedDictionary InsertValues {
			get { return _InsertValues; }
			set { _InsertValues = value; }
		}

		protected GridViewRow gvFooterRow = null;
		public override GridViewRow FooterRow {
			get {	return gvFooterRow == null ? base.FooterRow : gvFooterRow;	}
		}

		[Category("Action")]
		public event GridViewUpdatedEventHandler RowInserted {
			add		{	base.Events.AddHandler(InsertableGrid.EventItemInserted, value);		}
			remove	{	base.Events.RemoveHandler(InsertableGrid.EventItemInserted, value);		}
		}

		[Category("Action")]
		public event GridViewUpdateEventHandler RowInserting {
			add { base.Events.AddHandler(InsertableGrid.EventItemInserting, value); }
			remove { base.Events.RemoveHandler(InsertableGrid.EventItemInserting, value); }
		}


		protected int CreateChildControls1 (System.Collections.IEnumerable dataSource, bool dataBinding) {
			int ret = base.CreateChildControls(dataSource, dataBinding);
			if (Columns.Count == 0 || DesignMode || !AllowInsert)
				return ret;
			ShowFooter = true;
			DataControlField[] flds = new DataControlField[Columns.Count];
			Columns.CopyTo(flds, 0);
			if (ret == 0) {
				Controls.Clear();
				Table t = new Table();
				Controls.Add(t);

				GridViewRow r = CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
				this.InitializeRow(r, flds);
				t.Rows.Add(r);

				gvFooterRow = CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Insert);
				this.InitializeRow(gvFooterRow, flds);
				t.Rows.Add(gvFooterRow);
			}
			else 
				gvFooterRow = base.FooterRow;
			FooterRow.RowState = DataControlRowState.Insert;
			FooterRow.Visible = (base.EditIndex < 0);
			for (int i = 0; i < Columns.Count; i++) {
				DataControlFieldCell cell = (DataControlFieldCell)FooterRow.Cells[i];
				DataControlField fld = Columns[i];
				fld.InsertVisible = fld.Visible;
				if (fld is CommandField) {
					CommandField cf = (CommandField)fld;
					CommandField ins = new CommandField();
					ins.ButtonType = cf.ButtonType;
					ins.InsertImageUrl = cf.InsertImageUrl;
					ins.InsertText = cf.InsertText;
					ins.CancelImageUrl = cf.CancelImageUrl;
					ins.CancelText = cf.CancelText;
					ins.InsertVisible = true;
					ins.ShowInsertButton = true;
					ins.Initialize(false, this);
					ins.InitializeCell(cell, DataControlCellType.DataCell, DataControlRowState.Insert, -1);
				}
				else if (cell.Controls.Count == 0) { //don't overwrite any existing controls
					fld.Initialize(base.AllowSorting, this);
					fld.InitializeCell(cell, DataControlCellType.DataCell, DataControlRowState.Edit | DataControlRowState.Insert, -1);
				}
			}
			OrderedDictionary dict = new OrderedDictionary();
			base.ExtractRowValues(dict, FooterRow, true, true);
			DataTable tbl = new DataTable();
			DataRow row = tbl.Rows.Add();
			foreach (string k in dict.Keys) {
				tbl.Columns.Add(new DataColumn(k));
				row[k] = dict[k];
			}
			FooterRow.DataItem = new DataView(tbl)[0];
			GridViewRowEventArgs args1 = new GridViewRowEventArgs(FooterRow);
			this.OnRowCreated(args1);
			FooterRow.DataBind();
			this.OnRowDataBound(args1);
			FooterRow.DataItem = null;
			foreach (DataControlField f in Columns)
				f.Initialize(this.AllowSorting, this);
			return ret;
		}

		protected virtual void OnRowInserting(GridViewUpdateEventArgs e) {
			GridViewUpdateEventHandler h = (GridViewUpdateEventHandler)base.Events[InsertableGrid.EventItemInserting];
			if (h != null) 
				h(this, e);
		}

		protected virtual void OnRowInserted(GridViewUpdatedEventArgs e) {
			GridViewUpdatedEventHandler h = (GridViewUpdatedEventHandler)base.Events[InsertableGrid.EventItemInserted];
			if (h != null)
				h(this, e);
		}

		protected override void OnRowCommand(GridViewCommandEventArgs e) {
			if ("-1".Equals(e.CommandArgument) && "Cancel".CompareTo(e.CommandName) == 0) {
				Page.Trace.Warn("Canceling insert...");
				return;
			}
			if ("-1".Equals(e.CommandArgument) && "Insert".Equals(e.CommandName)
			&& this.Page != null && this.Page.IsValid) {
				GridViewUpdateEventArgs args = new GridViewUpdateEventArgs(-1);
				base.ExtractRowValues(args.NewValues, FooterRow, true, true);
				InsertValues = args.NewValues;
				bool allEmpty = true;
				foreach (string v in InsertValues.Values) 
					if ((allEmpty = (v == null || v.Trim().Length == 0)) == false)
						break;
				if (allEmpty)
					return;
				this.OnRowInserting(args);
				if (args.Cancel)
					return;
				DataSourceView view = this.GetData();
				view.Insert(args.NewValues, delegate(int affectedRows, Exception ex) {
					GridViewUpdatedEventArgs evt = new GridViewUpdatedEventArgs(affectedRows, ex);
					evt.NewValues.Clear();
					foreach (string v in InsertValues.Keys)
						evt.NewValues.Add(v, InsertValues[v]);
					this.OnRowInserted(evt);
					if (ex != null && !evt.ExceptionHandled)
						return false;
					base.RequiresDataBinding = true;
					return true;
				});
				return;
			}
			base.OnRowCommand(e);
		}

	  private void PrepareDropDowns(bool addBlank)
	  {
	    foreach (TableCell t in FooterRow.Cells)
	    {
	      foreach (Control c in t.Controls)
	      {
	        DropDownList ddl = c as DropDownList;

	        if (ddl != null && !ddl.DataSourceID.Equals(""))
	        {
	          if (addBlank)
	          {
	            ddl.AppendDataBoundItems = true;
	            ddl.Items.Insert(0, "");
	          }
	          else
	          {
	            ddl.SelectedIndex = 1;
	            ddl.Items.RemoveAt(0);
	          }
	        }
	      }
	    }
	  }

//Swap your CreateChildControls routine to this:

	  protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
	  {
	    int ret = base.CreateChildControls(dataSource, dataBinding);
	    if (Columns.Count == 0 || DesignMode || !AllowInsert)
	      return ret;
	    ShowFooter = true;
	    DataControlField[] flds = new DataControlField[Columns.Count];
	    Columns.CopyTo(flds, 0);
	    if (ret == 0)
	    {
	      Controls.Clear();
	      Table t = new Table();
	      Controls.Add(t);

	      GridViewRow r = CreateRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal);
	      this.InitializeRow(r, flds);
	      t.Rows.Add(r);

	      gvFooterRow = CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Insert);
	      this.InitializeRow(gvFooterRow, flds);
	      t.Rows.Add(gvFooterRow);
	    }
	    else
	      gvFooterRow = base.FooterRow;
	    FooterRow.RowState = DataControlRowState.Insert;
	    FooterRow.Visible = (base.EditIndex < 0);
	    for (int i = 0; i < Columns.Count; i++)
	    {
	      DataControlFieldCell cell = (DataControlFieldCell) FooterRow.Cells[i];
	      DataControlField fld = Columns[i];
	      fld.InsertVisible = fld.Visible;
	      if (fld is CommandField)
	      {
	        CommandField cf = (CommandField) fld;
	        CommandField ins = new CommandField();
	        ins.ButtonType = cf.ButtonType;
	        ins.InsertImageUrl = cf.InsertImageUrl;
	        ins.InsertText = cf.InsertText;
	        ins.CancelImageUrl = cf.CancelImageUrl;
	        ins.CancelText = cf.CancelText;
	        ins.InsertVisible = true;
	        ins.ShowInsertButton = true;
	        ins.Initialize(false, this);
	        ins.InitializeCell(cell, DataControlCellType.DataCell, DataControlRowState.Insert, -1);
	      }
	      else if (cell.Controls.Count == 0)
	      {
	        //don't overwrite any existing controls
	        fld.Initialize(base.AllowSorting, this);
	        fld.InitializeCell(cell, DataControlCellType.DataCell, DataControlRowState.Edit | DataControlRowState.Insert,
	                           -1);
	        PrepareDropDowns(true);
	      }
	    }
	    OrderedDictionary dict = new OrderedDictionary();
	    base.ExtractRowValues(dict, FooterRow, true, true);
	    DataTable tbl = new DataTable();
	    DataRow row = tbl.Rows.Add();
	    foreach (string k in dict.Keys)
	    {
	      tbl.Columns.Add(new DataColumn(k));
	      row[k] = dict[k];
	    }
	    FooterRow.DataItem = new DataView(tbl)[0];
	    GridViewRowEventArgs args1 = new GridViewRowEventArgs(FooterRow);
	    this.OnRowCreated(args1);
	    FooterRow.DataBind();
	    this.OnRowDataBound(args1);
	    FooterRow.DataItem = null;
	    foreach (DataControlField f in Columns)
	      f.Initialize(this.AllowSorting, this);
	    PrepareDropDowns(false);
	    return ret;
	  }
	}
}
